package io.gitee.zhangbinhub.acp.cloud.log.consumer

import io.gitee.zhangbinhub.acp.cloud.log.AcpCloudLogLevel
import io.gitee.zhangbinhub.acp.cloud.log.AcpCloudLogInfo
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.acp.core.common.exceptions.EnumValueUndefinedException
import io.gitee.zhangbinhub.acp.core.common.log.LogFactory
import io.gitee.zhangbinhub.acp.core.common.task.BaseAsyncTask
import io.gitee.zhangbinhub.acp.core.common.task.threadpool.ThreadPoolService

/**
 * 默认日志消息处理类
 * 如需自定义，请实现 LogProcess 接口
 *
 * @since JDK 17
 */
class DefaultLogProcess : LogProcess {

    override fun process(acpCloudLogInfo: AcpCloudLogInfo) {
        // 每个日志类型启动一个线程池，池中仅有一个线程，保证每个类型的消息顺序处理
        val threadPoolService = ThreadPoolService.getInstance(1, 1, Int.MAX_VALUE, acpCloudLogInfo.logType + "_log")
        threadPoolService.addTask(object : BaseAsyncTask(acpCloudLogInfo.logType + "_log", false) {
            override fun beforeExecuteFun(): Boolean = true
            override fun executeFun(): Any {
                doLog(acpCloudLogInfo)
                return true
            }

            override fun afterExecuteFun(result: Any) {}
        })
    }

    private fun doLog(acpCloudLogInfo: AcpCloudLogInfo) {
        val logFactory = LogFactory.getInstance(acpCloudLogInfo.logType)
        val acpCloudLogLevel: AcpCloudLogLevel = try {
            AcpCloudLogLevel.getEnum(acpCloudLogInfo.logLevel!!)
        } catch (e: EnumValueUndefinedException) {
            logFactory.error(e.message, e)
            AcpCloudLogLevel.Other
        }
        val message = StringBuilder()
            .append("[ ").append(CommonTools.strFillIn(acpCloudLogLevel.name, 5, 1, ' ')).append(" ] ")
            .append("[").append(acpCloudLogInfo.serverName ?: "").append("] ")
            .append("[ip:").append(acpCloudLogInfo.serverIp ?: "").append("] ")
            .append("[port:").append(acpCloudLogInfo.serverPort ?: "").append("] ")
            .append("[").append(acpCloudLogInfo.className ?: "").append("] ")
            .append("[").append(acpCloudLogInfo.lineNo).append("] ")
            .append("[traceId:").append(acpCloudLogInfo.traceId ?: "").append("] ")
            .append("[spanId:").append(acpCloudLogInfo.spanId ?: "").append("] - ")
            .append(acpCloudLogInfo.message ?: "")
        when (acpCloudLogLevel) {
            AcpCloudLogLevel.Debug -> {
                if (acpCloudLogInfo.params.isNotEmpty()) {
                    logFactory.debug(message.toString(), *acpCloudLogInfo.params.toTypedArray())
                } else {
                    logFactory.debug(message.toString())
                }
            }

            AcpCloudLogLevel.Warn -> {
                if (acpCloudLogInfo.params.isNotEmpty()) {
                    logFactory.warn(message.toString(), *acpCloudLogInfo.params.toTypedArray())
                } else {
                    logFactory.warn(message.toString())
                }
            }

            AcpCloudLogLevel.Error -> {
                if (acpCloudLogInfo.params.isNotEmpty()) {
                    logFactory.error(message.toString(), *acpCloudLogInfo.params.toTypedArray())
                } else {
                    logFactory.error(message.toString())
                }
            }

            AcpCloudLogLevel.Trace -> {
                if (acpCloudLogInfo.params.isNotEmpty()) {
                    logFactory.trace(message.toString(), *acpCloudLogInfo.params.toTypedArray())
                } else {
                    logFactory.trace(message.toString())
                }
            }

            else -> {
                if (acpCloudLogInfo.params.isNotEmpty()) {
                    logFactory.info(message.toString(), *acpCloudLogInfo.params.toTypedArray())
                } else {
                    logFactory.info(message.toString())
                }
            }
        }
    }

}
